package com.swizipuremvc.core.utils
{
	import flash.utils.Dictionary;
	import flash.utils.describeType;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;

	public class Enum
	{
		private static var _map:Dictionary = new Dictionary();

		private static var _nameMap:Dictionary = new Dictionary();

		private static var _enumsSetMap:Dictionary = new Dictionary();

		private var _code:Object;

		public function Enum(code:Object)
		{
			var clazzName:String = getQualifiedClassName(this);
			if (_map[clazzName] == null)
			{
				_map[clazzName] = new Object();
				_enumsSetMap[clazzName] = [];
			}
			if (_map[clazzName][code] != null)
			{
				throw new Error("Enum '" + clazzName + "' with code '" + code + "' already exist");
			}
			_code = code;
			_map[clazzName][_code] = this;
			_enumsSetMap[clazzName].push(this);
		}

		public function toString():String
		{
			return _code.toString();
		}

		public function get enumName():String
		{
			this._name = _nameMap[this];
			if (!_name)
			{
				var clazz:Class = getDefinitionByName(getQualifiedClassName(this)) as Class;
				var classInfo:XML = describeType(clazz);
				for each (var staticConst:XML in classInfo..constant)
				{
					if (this == clazz[staticConst.@name])
					{
						_name = staticConst.@name;
						_nameMap[this] = _name;
						break;
					}
				}
			}
			return this._name;
		}

		private var _name:String;

		public function set enumName(name:String):void
		{
			this._name = name;
		}

		public function get code():Object
		{
			return _code;
		}

		public static function size(clazz:Class):uint
		{
			return _map[getQualifiedClassName(clazz)].length;
		}

		public static function byCode(clazz:Class, code:Object):Enum
		{
			return _map[getQualifiedClassName(clazz)][code];
		}

		public static function toArray(clazz:Class):Array
		{
			return _enumsSetMap[getQualifiedClassName(clazz)].concat();
		}
	}
}
